/**
 * 
 */
package com.google.code.netz.wfe;

import com.google.code.netz.wfe.api.ILifecycleHandler;
import com.google.code.netz.wfe.api.IWorkflowContext;
import com.google.code.netz.wfe.api.WorkflowException;
import com.google.code.netz.wfe.events.ActivityEvent;
import com.google.code.netz.wfe.events.EventManager;
import com.google.code.netz.wfe.events.ActivityEvent.EventType;
import com.google.code.netz.wfe.model.Activity;
import com.google.code.netz.wfe.model.State;

/**
 * 
 * @author <a href='mailto:rahul.thakur.xdev@gmail.com'>Rahul Thakur</a>
 * @since 1.0
 * @version $Id: ActivityLifecycleHandler.java 17 2009-02-09 13:08:49Z rahul.thakur.xdev $
 */
public class ActivityLifecycleHandler implements ILifecycleHandler<Activity> {

	/**
	 * Mutex to lock state updates to the Transition.
	 */
	private static Object mutex = new Object();

	/**
	 * {@inheritDoc}
	 * 
	 * @see com.google.code.netz.wfe.api.ILifecycleHandler#resume(com.google.code
	 *      .netz.wfe.api.IManaged, IWorkflowContext)
	 */
	@Override
	public void resume(Activity entity, IWorkflowContext workflowContext) throws WorkflowException {
		// TODO Auto-generated method stub
		synchronized (mutex) {
			if (entity.getCurrentState() == State.STATE_SUSPENDED) {
				entity.setCurrentState(State.STATE_RUNNING);
				EventManager.getInstance()
						.dispatchEvent(new ActivityEvent<Activity>(entity, EventType.ACTIVITY_OPENED));
			} else
				throw new WorkflowException(String.format(
						"Activity %s could not be resumed, it is not in a suspended state.", entity));
		}
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see com.google.code.netz.wfe.api.ILifecycleHandler#start(com.google.code.
	 *      netz.wfe.api.IManaged, IWorkflowContext)
	 */
	@Override
	public void start(Activity entity, IWorkflowContext workflowContext) throws WorkflowException {
		synchronized (mutex) {
			// TODO: Activity status should be updated in a synchronized block
			if (entity.getCurrentState() == State.STATE_DEFAULT) {
				entity.setCurrentState(State.STATE_ENABLED);
				EventManager.getInstance()
						.dispatchEvent(new ActivityEvent<Activity>(entity, EventType.ACTIVITY_OPENED));
			} else
				throw new WorkflowException(String.format(
						"Activity %s could not be started, it is not in a default state.", entity));
		}
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see com.google.code.netz.wfe.api.ILifecycleHandler#stop(com.google.code.netz
	 *      .wfe.api.IManaged, IWorkflowContext)
	 */
	@Override
	public void stop(Activity entity, IWorkflowContext workflowContext) throws WorkflowException {
		synchronized (mutex) {
			// TODO: Activity status should be updated in a synchronized block
			if (entity.getCurrentState() == State.STATE_RUNNING) {
				entity.setCurrentState(State.STATE_COMPLETED);
				EventManager.getInstance()
						.dispatchEvent(new ActivityEvent<Activity>(entity, EventType.ACTIVITY_CLOSED));
			} else
				throw new WorkflowException(String.format(
						"Activity %s could not be started, it is not in a default state.", entity));
		}
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see com.google.code.netz.wfe.api.ILifecycleHandler#suspend(com.google.code
	 *      .netz.wfe.api.IManaged, IWorkflowContext)
	 */
	@Override
	public void suspend(Activity entity, IWorkflowContext workflowContext) throws WorkflowException {
		synchronized (mutex) {
			// TODO: Activity status should be updated in a synchronized block
			if (entity.getCurrentState() == State.STATE_RUNNING) {
				entity.setCurrentState(State.STATE_SUSPENDED);
				EventManager.getInstance().dispatchEvent(
						new ActivityEvent<Activity>(entity, EventType.ACTIVITY_SUSPENDED));
			} else
				throw new WorkflowException(String.format(
						"Activity %s could not be suspended, it is not currently running.", entity));
		}
	}

}
